﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Ue.CQRS.Samples.Infrastructure.Data;

namespace Ue.CQRS.Samples.Application.Query.Repositories
{
    public class RepositoryFactory
    {
        private static ConcurrentDictionary<string, object> repositories = new ConcurrentDictionary<string, object>();

        public static IRepository<Guid, T> GetRepository<T>()
        {
            var entityTypeName = typeof(T).FullName;

            return repositories.GetOrAdd(entityTypeName, typeName => new ConcurrentRepository<T>()) as IRepository<Guid, T>;

        }
    }

    public static class IRepositoryExtensions
    {
        public static TValue GetOrAdd<TKey, TValue>(this IRepository<TKey, TValue> repository, TKey key, TValue entity)
        {
            return repository.GetOrAdd(key, k => entity);
        }

        public static TValue AddOrUpdate<TKey, TValue>(this IRepository<TKey, TValue> repository, TKey key, TValue entity)
        {
            return repository.AddOrUpdate(key, k => entity, (k, v) => entity);
        }

        public static TValue AddOrUpdate<TKey, TValue>(this IRepository<TKey, TValue> repository, TKey key, Func<TKey, TValue> entityFactory)
        {
            return repository.AddOrUpdate(key, entityFactory, (k, v) => entityFactory(k));
        }

        public static IEnumerable<TValue> FindBy<TKey, TValue>(this IRepository<TKey, TValue> repository, Expression<Func<TValue, bool>> predicate)
        {
            return repository.FindBy(predicate, null, null);
        }

    }
}